home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / pyxmpp / streamtls.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  9KB  |  311 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. __revision__ = '$Id: streamtls.py 667 2006-12-11 16:48:59Z jajcus $'
  5. __docformat__ = 'restructuredtext en'
  6. import socket
  7. import sys
  8. import errno
  9. import logging
  10. from pyxmpp.streambase import StreamBase, STREAM_NS
  11. from pyxmpp.streambase import FatalStreamError, StreamEncryptionRequired
  12. from pyxmpp.exceptions import TLSNegotiationFailed, TLSError, TLSNegotiatedButNotAvailableError
  13.  
  14. try:
  15.     import M2Crypto
  16.     if M2Crypto.version_info < (0, 16):
  17.         tls_available = 0
  18.     else:
  19.         from M2Crypto import SSL
  20.         from M2Crypto.SSL import SSLError
  21.         import M2Crypto.SSL.cb as M2Crypto
  22.         tls_available = 1
  23. except ImportError:
  24.     tls_available = 0
  25.  
  26. if not tls_available:
  27.     
  28.     class SSLError(Exception):
  29.         pass
  30.  
  31.  
  32. TLS_NS = 'urn:ietf:params:xml:ns:xmpp-tls'
  33.  
  34. class TLSSettings:
  35.     
  36.     def __init__(self, require = False, verify_peer = True, cert_file = None, key_file = None, cacert_file = None, verify_callback = None, ctx = None):
  37.         self.require = require
  38.         self.ctx = ctx
  39.         self.verify_peer = verify_peer
  40.         self.cert_file = cert_file
  41.         self.cacert_file = cacert_file
  42.         self.key_file = key_file
  43.         self.verify_callback = verify_callback
  44.  
  45.  
  46.  
  47. class StreamTLSMixIn:
  48.     tls_available = tls_available
  49.     
  50.     def __init__(self, tls_settings = None):
  51.         self.tls_settings = tls_settings
  52.         self._StreamTLSMixIn__logger = logging.getLogger('pyxmpp.StreamTLSMixIn')
  53.  
  54.     
  55.     def _reset_tls(self):
  56.         self.tls = None
  57.         self.tls_requested = False
  58.  
  59.     
  60.     def _make_stream_tls_features(self, features):
  61.         if self.tls_settings and not (self.tls):
  62.             tls = features.newChild(None, 'starttls', None)
  63.             ns = tls.newNs(TLS_NS, None)
  64.             tls.setNs(ns)
  65.             if self.tls_settings.require:
  66.                 tls.newChild(None, 'required', None)
  67.             
  68.         
  69.         return features
  70.  
  71.     
  72.     def _write_raw(self, data):
  73.         logging.getLogger('pyxmpp.Stream.out').debug('OUT: %r', data)
  74.         
  75.         try:
  76.             if self.tls:
  77.                 self.tls.setblocking(True)
  78.             
  79.             self.socket.send(data)
  80.             if self.tls:
  81.                 self.tls.setblocking(False)
  82.         except (IOError, OSError, socket.error):
  83.             e = None
  84.             raise FatalStreamError('IO Error: ' + str(e))
  85.         except SSLError:
  86.             e = None
  87.             raise TLSError('TLS Error: ' + str(e))
  88.  
  89.  
  90.     
  91.     def _read_tls(self):
  92.         if self.eof:
  93.             return None
  94.         
  95.         while self.socket:
  96.             
  97.             try:
  98.                 r = self.socket.read()
  99.                 if r is None:
  100.                     return None
  101.             except socket.error:
  102.                 e = None
  103.                 if e.args[0] != errno.EINTR:
  104.                     raise 
  105.                 
  106.                 return None
  107.  
  108.             self._feed_reader(r)
  109.  
  110.     
  111.     def _read(self):
  112.         self._StreamTLSMixIn__logger.debug('StreamTLSMixIn._read(), socket: %r', self.socket)
  113.         if self.tls:
  114.             self._read_tls()
  115.         else:
  116.             StreamBase._read(self)
  117.  
  118.     
  119.     def _process(self):
  120.         
  121.         try:
  122.             StreamBase._process(self)
  123.         except SSLError:
  124.             e = None
  125.             self.close()
  126.             raise TLSError('TLS Error: ' + str(e))
  127.  
  128.  
  129.     
  130.     def _process_node_tls(self, xmlnode):
  131.         ns_uri = xmlnode.ns().getContent()
  132.         if ns_uri == STREAM_NS:
  133.             return False
  134.         elif ns_uri == TLS_NS:
  135.             self._process_tls_node(xmlnode)
  136.             return True
  137.         
  138.         if self.tls_settings and self.tls_settings.require and not (self.tls):
  139.             raise StreamEncryptionRequired, 'TLS encryption required and not started yet'
  140.         
  141.         return False
  142.  
  143.     
  144.     def _handle_tls_features(self):
  145.         ctxt = self.doc_in.xpathNewContext()
  146.         ctxt.setContextNode(self.features)
  147.         ctxt.xpathRegisterNs('tls', TLS_NS)
  148.         
  149.         try:
  150.             tls_n = ctxt.xpathEval('tls:starttls')
  151.             tls_required_n = ctxt.xpathEval('tls:starttls/tls:required')
  152.         finally:
  153.             ctxt.xpathFreeContext()
  154.  
  155.         if not self.tls:
  156.             if tls_required_n and not (self.tls_settings):
  157.                 raise FatalStreamError, 'StartTLS support disabled, but required by peer'
  158.             
  159.             if self.tls_settings and self.tls_settings.require and not tls_n:
  160.                 raise FatalStreamError, 'StartTLS required, but not supported by peer'
  161.             
  162.             if self.tls_settings and tls_n:
  163.                 self._StreamTLSMixIn__logger.debug('StartTLS negotiated')
  164.                 if not self.tls_available:
  165.                     raise TLSNegotiatedButNotAvailableError, 'StartTLS negotiated, but not available (M2Crypto >= 0.16 module required)'
  166.                 
  167.                 if self.initiator:
  168.                     self._request_tls()
  169.                 
  170.             else:
  171.                 self._StreamTLSMixIn__logger.debug('StartTLS not negotiated')
  172.         
  173.  
  174.     
  175.     def _request_tls(self):
  176.         self.tls_requested = 1
  177.         self.features = None
  178.         root = self.doc_out.getRootElement()
  179.         xmlnode = root.newChild(None, 'starttls', None)
  180.         ns = xmlnode.newNs(TLS_NS, None)
  181.         xmlnode.setNs(ns)
  182.         self._write_raw(xmlnode.serialize(encoding = 'UTF-8'))
  183.         xmlnode.unlinkNode()
  184.         xmlnode.freeNode()
  185.  
  186.     
  187.     def _process_tls_node(self, xmlnode):
  188.         if not (self.tls_settings) or not tls_available:
  189.             self._StreamTLSMixIn__logger.debug('Unexpected TLS node: %r' % xmlnode.serialize())
  190.             return False
  191.         
  192.         if self.initiator:
  193.             if xmlnode.name == 'failure':
  194.                 raise TLSNegotiationFailed, 'Peer failed to initialize TLS connection'
  195.             elif xmlnode.name != 'proceed' or not (self.tls_requested):
  196.                 self._StreamTLSMixIn__logger.debug('Unexpected TLS node: %r' % xmlnode.serialize())
  197.                 return False
  198.             
  199.             
  200.             try:
  201.                 self.tls_requested = 0
  202.                 self._make_tls_connection()
  203.                 self.socket = self.tls
  204.             except SSLError:
  205.                 e = None
  206.                 self.tls = 0
  207.                 raise TLSError('TLS Error: ' + str(e))
  208.  
  209.             self._StreamTLSMixIn__logger.debug('Restarting XMPP stream')
  210.             self._restart_stream()
  211.             return True
  212.         else:
  213.             raise FatalStreamError, 'TLS not implemented for the receiving side yet'
  214.  
  215.     
  216.     def _make_tls_connection(self):
  217.         if not tls_available or not (self.tls_settings):
  218.             raise TLSError, 'TLS is not available'
  219.         
  220.         self.state_change('tls connecting', self.peer)
  221.         self._StreamTLSMixIn__logger.debug('Creating TLS context')
  222.         if self.tls_settings.ctx:
  223.             ctx = self.tls_settings.ctx
  224.         else:
  225.             ctx = SSL.Context('tlsv1')
  226.         verify_callback = self.tls_settings.verify_callback
  227.         if not verify_callback:
  228.             verify_callback = self.tls_default_verify_callback
  229.         
  230.         if self.tls_settings.verify_peer:
  231.             self._StreamTLSMixIn__logger.debug('verify_peer, verify_callback: %r', verify_callback)
  232.             ctx.set_verify(SSL.verify_peer, 10, verify_callback)
  233.         else:
  234.             ctx.set_verify(SSL.verify_none, 10)
  235.         if self.tls_settings.cert_file:
  236.             ctx.use_certificate_chain_file(self.tls_settings.cert_file)
  237.             if self.tls_settings.key_file:
  238.                 ctx.use_PrivateKey_file(self.tls_settings.key_file)
  239.             else:
  240.                 ctx.use_PrivateKey_file(self.tls_settings.cert_file)
  241.             ctx.check_private_key()
  242.         
  243.         if self.tls_settings.cacert_file:
  244.             
  245.             try:
  246.                 ctx.load_verify_location(self.tls_settings.cacert_file)
  247.             except AttributeError:
  248.                 ctx.load_verify_locations(self.tls_settings.cacert_file)
  249.             except:
  250.                 None<EXCEPTION MATCH>AttributeError
  251.             
  252.  
  253.         None<EXCEPTION MATCH>AttributeError
  254.         self._StreamTLSMixIn__logger.debug('Creating TLS connection')
  255.         self.tls = SSL.Connection(ctx, self.socket)
  256.         self._StreamTLSMixIn__logger.debug('Setting up TLS connection')
  257.         self.tls.setup_ssl()
  258.         self._StreamTLSMixIn__logger.debug('Setting TLS connect state')
  259.         self.tls.set_connect_state()
  260.         self._StreamTLSMixIn__logger.debug('Starting TLS handshake')
  261.         self.tls.connect_ssl()
  262.         self.state_change('tls connected', self.peer)
  263.         self.tls.setblocking(0)
  264.         
  265.         try:
  266.             raise Exception
  267.         except:
  268.             pass
  269.  
  270.  
  271.     
  272.     def tls_is_certificate_valid(self, store_context):
  273.         depth = store_context.get_error_depth()
  274.         if depth > 0:
  275.             return True
  276.         
  277.         cert = store_context.get_current_cert()
  278.         cn = cert.get_subject().CN
  279.         if str(cn) != self.peer.as_utf8():
  280.             return False
  281.         
  282.         return True
  283.  
  284.     
  285.     def tls_default_verify_callback(self, ok, store_context):
  286.         
  287.         try:
  288.             self._StreamTLSMixIn__logger.debug('tls_default_verify_callback(ok=%i, store=%r)' % (ok, store_context))
  289.             X509 = X509
  290.             m2 = m2
  291.             import M2Crypto
  292.             depth = store_context.get_error_depth()
  293.             cert = store_context.get_current_cert()
  294.             cn = cert.get_subject().CN
  295.             self._StreamTLSMixIn__logger.debug('  depth: %i cert CN: %r' % (depth, cn))
  296.             if ok and not tls_is_certificate_valid(store_context):
  297.                 self._StreamTLSMixIn__logger.debug(u'Common name does not match peer name (%s != %s)' % (cn, self.peer.as_utf8))
  298.                 return False
  299.             
  300.             return ok
  301.         except:
  302.             self._StreamTLSMixIn__logger.exception('Exception caught')
  303.             raise 
  304.  
  305.  
  306.     
  307.     def get_tls_connection(self):
  308.         return self.tls
  309.  
  310.  
  311.